#ifndef _MATH_POWER_H_
#define _MATH_POWER_H_

#include"Constants.h"

template<class T>
T nthRoot(T a, int root){

	double Ni = 1.0/((double)root);
	int Nm = root - 1;
	
	double x = 1.0/((double)a * root);

	for(int i = 0; i < 20 ; i ++){
		double tmpx = x;
		for(int k = 0 ; k < root -2 ; k++){
			tmpx *= x;
		}
		x = Ni * ( Nm * x + ((double)a)/ tmpx);
	}
	return ((T)x);
}

template<class T>
T factorial(T n){
	n = (int)n;
	int factorial = 0;
	for (int i = 0; i <= n; i++)
		if (i == 0)
			factorial = 1;
		else
		factorial = factorial * i;
	return (T)factorial;
}

template <class T>
T ln(T a){
	int add = 0;
	double q = (double)a;
	while(q > E){ q/= E;add++;}
	double Z =  (q - 1) / (q + 1);
	double Y = Z * Z;
	double Y2 = Y*Y;
	double top = Z * 2;
	double A = 1155.0;
	double B = 1190 * Y;
	double C = 231 * Y2;
	double D = (A - B) + C;
	top *= D;
	double bottom = (A - (1575*Y) + 525*Y2 - 25*Y*Y2);
	return ((T)(top/bottom + add));
}
template<class T>
double log(T b){
	return logb(b,(int)10);
}
template <class T, class U>
T logb(T a, U base){
	return (T)(ln(a) /ln((T)base)) ;
}

template <class T>
T power(T k, int n){
	double x = k;
	double retval = 1;
	double factor = x;
	while(n != 0){
		if((n&1) != 0)
			retval *= factor;
			factor *= factor;
			n >>= 1;
		}
	return (T)retval;
}

template<class T>
T exp(T k){
	double x = k;
	const double root_e = fthRE;
	const double a= 1.000000034750736;
	const double b= 0.499997989964957;
	const double c= 0.166704077809886;
	const double d= 0.041365419657829;
	const double e= 9.419273457583088E-3;
	double retval;
	double intpart;
	int n;
	x *= 4;
	n = (int)x;
	x -= n;
	x /= 4;
	retval = ((((x*e+d)*x+c)*x+b)*x+a)*x+1;
	intpart = power(root_e,n);
	return (T)(intpart*retval);
}

template<class T, class U>
T pow(T x, U y)
{
	return (T)exp((T)y* ln(x));
}

#endif